home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / serial / dcon0.000 / dcon0 / dcon0.96 / dcon.c next >
C/C++ Source or Header  |  1996-07-20  |  29KB  |  1,183 lines

  1. /*
  2.  * dcon version 0.91 April 1996
  3.  *
  4.  * Copyright (C) 1989,1996  Daniel Chouinard
  5.  *
  6.  * Permission to use, copy, and distribute this software and its
  7.  * documentation for any purpose without fee is hereby granted,
  8.  * provided that the above copyright notice appear in all copies and
  9.  * that both that copyright notice and this permission notice appear
  10.  * in supporting documentation.
  11.  *
  12.  * Permission to modify the software is granted, but not the right to
  13.  * distribute the modified code so that only one version of the language
  14.  * syntax may be agreed upon.
  15.  *
  16.  * This software is provided "as is" without express or implied warranty.
  17.  *
  18.  * See dcon.doc for more information.
  19.  */
  20.  
  21. /*
  22. *
  23. * Bugs:
  24. *
  25. * getvalue() evaluates from left to right and doesn't respect mathematical
  26. * conventions. ie. 5*3+1 evaluates to 20 because 3+1 is evaluated first and
  27. * then 5 times that.  Parenthesis can be used in the mean time. (ie. (5*3)+1)
  28. * 5-3+1, no better, evaluates to 1.
  29. *
  30. */
  31.  
  32. #include <stdio.h>
  33. #include <signal.h>
  34. #include <sys/time.h>
  35. #include <sys/types.h>
  36. #include <termio.h>
  37. #include <fcntl.h>
  38.  
  39. #define MAXGOSUBS 32  /* Max depth */
  40. #define STRINGL 512   /* String lengths.  Also, max script line length */
  41. #define MAXPATH 512   /* Max filename length (less or equal to STRINGL) */
  42. #define MAXTOKEN 20   /* Maximum token or label length */
  43.  
  44. #define BOOL unsigned char
  45.  
  46. FILE *filep;
  47. unsigned char *script;
  48. int scriptspace;
  49. BOOL ifres;
  50. int lastpc,pc; /* program "counters" */
  51. long resultcode=0; /* result code */
  52. int ignorecase=1;  /* no case sensitivity */
  53. BOOL comecho=0; /* echo what's comin' in */
  54. long senddelay=0; /* 0/100th second character delay for sending */
  55. long number;  /* For getonearg() returning an long */
  56. long intvars[26]; /* [a-z] integer variables */
  57. char string[STRINGL]; /* For getstring() returns and misc. use (misuse) */
  58. char stringvars[26][STRINGL]; /* $[a-z] string variables (Should be malloced) */
  59. char cspeed[10];  /* Ascii representation of baudrate */
  60. int speed=B2400; /* Set to B110, B150, B300,..., B38400 */
  61. char device[MAXPATH]; /* Comm device.  May be "-" */
  62. char token[MAXTOKEN];   /* For gettoken() returns */
  63. char scriptfile[MAXPATH]; /* Script file name */
  64. BOOL verbose=0; /* Log actions */
  65. struct termio cons, stbuf, svbuf;  /* termios: svbuf=before, stbuf=while */
  66. int comfd= -1; /* Communication file descriptor.  May be 0 */
  67. char msg[STRINGL]; /* Massage messages here */
  68. int preturn,returns[MAXGOSUBS];
  69. int clocal=0;
  70. int parity=0, bits=CS8, stopbits=0;
  71. unsigned long hstart,hset;
  72. BOOL lastcharnl=1; /* Indicate that last char printed from getonebyte
  73.                                was a nl, so no new one is needed */
  74.  
  75. /* Returns hundreds of seconds */
  76. long htime() {
  77.   struct timeval timenow;
  78.   gettimeofday(&timenow,NULL);
  79.   return(100L*(timenow.tv_sec-hstart)+(timenow.tv_usec)/10000L-hset);
  80. }
  81.  
  82. /* I use select() 'cause CX/UX 6.2 doesn't have usleep().
  83.    On Linux, usleep() uses select() anyway.
  84. */
  85. void dormir(unsigned long microsecs) {
  86.   struct timeval timeout;
  87.   timeout.tv_sec=microsecs/1000000L;
  88.   timeout.tv_usec=microsecs-(timeout.tv_sec*1000000L);
  89.   select(1,(fd_set *)0,(fd_set *)0,(fd_set *)0,&timeout);
  90. }
  91.  
  92. /* Tests for ENTER key */
  93. void dotestkey() {
  94.   fd_set fds[2];
  95.   struct timeval timeout;
  96.   timeout.tv_sec=0L;
  97.   timeout.tv_usec=10000L;
  98.   FD_ZERO(fds);
  99.   FD_SET(0,fds);  /* Prepare to select() from stdin */
  100.   resultcode=select(1,fds,0,0,&timeout);
  101.   if(resultcode) getchar();
  102. }
  103.  
  104. /* Exit after resetting terminal settings */
  105. void ext(long xtc) {
  106.   ioctl(1, TCSETA, &cons);
  107.   exit(xtc);
  108. }
  109.  
  110. /* Log message if verbose is on */
  111. void vmsg(char *text) {
  112.   time_t t;
  113.   char *ct;
  114.   if(verbose) {
  115.     if(lastcharnl==0) {
  116.       fprintf(stderr,"\n");
  117.       lastcharnl=1;
  118.     }
  119.     t=time(0);
  120.     ct=ctime(&t);
  121.     fprintf(stderr,"dcon %c%c:%c%c:%c%c -> %s\r\n",
  122.             ct[11],ct[12],ct[14],ct[15],ct[17],ct[18],
  123.             text);
  124.   }
  125. }
  126.  
  127. /* Skip to next statement */
  128. void skipline() {
  129.   while(script[pc]!='\n' && script[pc]!=0) pc++;
  130.   if(script[pc]) pc++;
  131. }
  132.  
  133. void printwhere() {
  134.   int a,b,c;
  135.   sprintf(msg,"@%04d ",pc);
  136.   a=pc;
  137.   skipline();
  138.   b=pc-1;
  139.   pc=a;
  140.   c=strlen(msg);
  141.   for(;a<b;a++) msg[c++]=script[a];
  142.   msg[c]=0;
  143.   vmsg(msg);
  144. }
  145.  
  146. /* Write a null-terminated string to communication device */
  147. void writecom(char *text) {
  148.   int res,a;
  149.   char ch;
  150.   for(a=0;a<strlen(text);a++) {
  151.     ch=text[a];
  152.     res=write(comfd,&ch,1);
  153.     if(senddelay) dormir(senddelay);
  154.     if(res!=1) {
  155.       fprintf(stderr,"Could not write to device!\n");
  156.       ext(1);
  157.     }
  158.   }
  159. }
  160.  
  161. /* Gets a single byte from comm. device.  Return -1 if none avail. */
  162. int getonebyte() {
  163.   int res;
  164.   char ch;
  165.   res=0;
  166.   res=read(comfd,&ch,1);
  167.   if(res==1) { 
  168.     if(comecho) {
  169.       if(ch=='\n') lastcharnl=1;
  170.       else {
  171.         if(ch!='\r') lastcharnl=0;
  172.       }
  173.       fputc(ch,stderr);
  174.     }
  175.     return(ch);
  176.   }
  177.   dormir(100000); /* No char received, wait 1/10th sec. */
  178.   return(-1);
  179. }
  180.  
  181. /* Report script errors and quit */
  182. void serror(char *text) {
  183.   int a,line;
  184.   if(verbose==0) {
  185.     verbose=1;
  186.     a=pc;
  187.     pc=lastpc;
  188.     printwhere();
  189.     pc=a;
  190.   }
  191.   strcpy(msg,"----> ");
  192.   for(a=6;a<STRINGL;a++) msg[a]=' ';
  193.   for(a=0;a<pc-lastpc;a++) {
  194.     if(script[a+lastpc]=='\t') msg[a+8]='\t';
  195.   }
  196.   a+=6;
  197.   msg[a++]='^';
  198.   msg[a]=0;
  199.   vmsg(msg);
  200.   a=0; line=1;
  201.   while(a<pc) {
  202.     if(script[a++]=='\n') {
  203.       if(a<pc) line++;
  204.     }
  205.   }
  206.   sprintf(msg,"Error @%d, line %d, %s.\n",pc,line,text);
  207.   vmsg(msg);
  208.   ext(1);
  209. }
  210.  
  211. void skipspaces() {
  212.   while(script[pc]==' ' || script[pc]=='\t' ) pc++;
  213. }
  214.  
  215. void getopen() {
  216.   skipspaces();
  217.   if(script[pc++]!='(') serror("Function requires open parenthesis");
  218. }
  219.  
  220. void getclose() {
  221.   skipspaces();
  222.   if(script[pc++]!=')') serror("Function requires close parenthesis");
  223. }
  224.  
  225. /* Parse script[pc] to get next statement.  Resolve comments and labels... */
  226. int gettoken() {
  227.   int tokenp=0;
  228.   skipspaces();
  229.   if(script[pc]=='=' || script[pc]=='<' || script[pc]=='>' || script[pc]=='!') {
  230.     if(script[pc]=='!') {
  231.       if(script[pc+1]!='=') serror("Invalid token. Use '!='");
  232.       strcpy(token,"!=");
  233.       pc+=2;
  234.       return(0);
  235.     }
  236.     token[0]=script[pc++];
  237.     token[1]=0;
  238.     return(0);
  239.   }
  240.   if(script[pc]=='#') {
  241.     strcpy(token,"rem");
  242.     pc++;
  243.     return(0);
  244.   }
  245.   if(script[pc]=='/' && script[pc+1]=='/') {
  246.     strcpy(token,"rem");
  247.     pc+=2;
  248.     return(0);
  249.   }
  250.   if(script[pc]==':') {
  251.     strcpy(token,"label");
  252.     pc++;
  253.     return(0);
  254.   }
  255.   while(script[pc]!=' ' && script[pc]!='\n' &&
  256.         script[pc]!='\t' && script[pc]!='(') {
  257.     token[tokenp]=script[pc++];
  258.     if(tokenp++==MAXTOKEN-1) serror("Token too long");
  259.   }
  260.   token[tokenp]=0;
  261.   skipspaces();
  262.   if(strcmp(token,"then")==0) gettoken(); /* Ignore then for if */
  263.   return(0);
  264. }
  265.  
  266. /* shitfaced recursive value parser. must write better one */
  267. long getvalue() {
  268.   unsigned long p=0;
  269.   int goone=1;
  270.   unsigned char index;
  271.   skipspaces();
  272.   if(script[pc]=='(') {
  273.     pc++;
  274.     p=getvalue();
  275.     getclose();
  276.   }
  277.   else if(script[pc]==')') {
  278.     return(p);
  279.   }
  280.   else if(script[pc]>='a' && script[pc]<='z' && script[pc+1]>='a' &&
  281.           script[pc+1]<='z') {
  282.     gettoken();
  283.     getopen();
  284.     if(strcmp(token,"len")==0) {
  285.       getstring();
  286.       p=strlen(string);
  287.     }
  288.     else if(strcmp(token,"htime")==0) {
  289.       p=htime();
  290.     }
  291.     else if(strcmp(token,"time")==0) {
  292.       p=time(0);
  293.     }
  294.     else if(strcmp(token,"pid")==0) {
  295.       p=getpid();
  296.     }
  297.     else if(strcmp(token,"ppid")==0) {
  298.       p=getppid();
  299.     }
  300.     else if(strcmp(token,"baud")==0) {
  301.       p=atol(cspeed);
  302.     }
  303.     else if(strcmp(token,"val")==0 || strcmp(token,"atol")==0) {
  304.       getstring();
  305.       p=atol(string);
  306.     }
  307.     else serror("Unknown Integer function");
  308.     getclose();
  309.   }
  310.   if(script[pc]=='%') {
  311.     pc++;
  312.     skipspaces();
  313.     p=resultcode;
  314.   }
  315.   while(goone) {
  316.     if(script[pc]=='+') {
  317.       pc++;
  318.       p+=getvalue();
  319.     }
  320.     else if(script[pc]=='-') {
  321.       pc++;
  322.       p-=getvalue();
  323.     }
  324.     else if(script[pc]=='^') {
  325.       pc++;
  326.       p^=getvalue();
  327.     }
  328.     else if(script[pc]=='&') {
  329.       pc++;
  330.       p&=getvalue();
  331.     }
  332.     else if(script[pc]=='|') {
  333.       pc++;
  334.       p|=getvalue();
  335.     }
  336.     else if(script[pc]=='*') {
  337.       pc++;
  338.       p*=getvalue();
  339.     }
  340.     else if(script[pc]=='/') {
  341.       pc++;
  342.       p/=getvalue();
  343.     }
  344.     else if((script[pc]>='a' && script[pc]<='z') ) {
  345.       index=script[pc++];
  346.       p=intvars[index-'a'];
  347.     }
  348.     else if(script[pc]>='0' && script[pc]<='9') { 
  349.       p=p*10+script[pc++]-'0';
  350.     }
  351.     else {
  352.       goone=0;
  353.     }
  354.   }
  355.   return(p);
  356. }
  357.  
  358. void getcomma() {
  359.   skipspaces();
  360.   if(script[pc++]!=',') serror("Comma expected");
  361. }
  362.  
  363. /* Parse a string from script[pc] */
  364. getstring() {
  365.   FILE *fp;
  366.   time_t t;
  367.   int a,b,c,p=0;
  368.   unsigned char index,ch,match;
  369.   string[0]=0;
  370.   skipspaces();
  371.   while(script[pc]!=' ' && script[pc]!='\t' && script[pc]!='\n' && script[pc]!=','  && script[pc]!=')' && script[pc]!='=' && script[pc]!='<' && script[pc]!='>' && script[pc]!='!' ) {
  372.     if(script[pc]=='+') pc++;
  373.     skipspaces();
  374.     if(script[pc]=='$' && script[pc+1]>='a' && script[pc+1]<='z' && 
  375.        script[pc+2]>='a' && script[pc+2]<='z') {
  376.       pc++;
  377.       gettoken();
  378.       getopen();
  379.       if(strcmp(token,"time")==0) {
  380.         t=time(0);
  381.         strcat(string,ctime(&t));
  382.         string[strlen(string)-1]=0;
  383.       }
  384.       else if(strcmp(token,"rpipe")==0) {
  385.         char toto[STRINGL];
  386.         strcpy(toto,string);
  387.         getstring();
  388.         if((fp=popen(string,"r"))==NULL) serror("Could not popen!");
  389.         fgets(string,STRINGL-1,fp);
  390.         string[strlen(string)-1]=0;
  391.         pclose(fp);
  392.         strcat(toto,string);
  393.         strcpy(string,toto);
  394.       }
  395.       else if(strcmp(token,"env")==0) {
  396.         getstring();
  397.         if(getenv(string)) strcpy(string,(char *)getenv(string));
  398.         else string[0]=0;
  399.       }
  400.       else if(strcmp(token,"hms")==0) {
  401.         long sec,min,hour;
  402.         sec=getvalue();
  403.         min=sec/60L;
  404.         sec-=min*60L;
  405.         hour=min/60L;
  406.         min-=hour*60L;
  407.         sprintf(string,"%s%02ld:%02ld:%02ld",string,hour,min,sec);
  408.       }
  409.       else if(strcmp(token,"dev")==0) {
  410.         strcat(string,device);
  411.       }
  412.       else if(strcmp(token,"cwd")==0) {
  413.         getcwd(string,STRINGL);
  414.       }
  415.       else if(strcmp(token,"baud")==0) {
  416.         strcat(string,cspeed);
  417.       }
  418.       else if(strcmp(token,"str")==0 || strcmp(token,"ltoa")==0) {
  419.         sprintf(string,"%ld",getvalue());
  420.       }
  421.       else if(strcmp(token,"mid")==0) {
  422.         char toto[STRINGL];
  423.         strcpy(toto,string);
  424.         getstring();
  425.         getcomma();
  426.         a=getvalue();
  427.         getcomma();
  428.         b=getvalue();
  429.         if(a>strlen(string)) serror("String is shorter than second argument");
  430.         c=strlen(toto);
  431.         while(b!=0 && string[a]!=0) {
  432.           toto[c++]=string[a++];
  433.           b--;
  434.         }
  435.         toto[c]=0;
  436.         strcpy(string,toto);
  437.       }
  438.       else serror("Invalid string funtion");
  439.       getclose();
  440.     }
  441.     else if(script[pc]=='$') {
  442.       index=script[++pc];
  443.       if(index<'a' || index>'z') serror("String variables are [a-z]");
  444.       strcat(string,stringvars[index-'a']);
  445.       pc++;
  446.     }
  447.     else if(script[pc]=='"' || script[pc]=='\'') {
  448.       match=script[pc++];
  449.       while(script[pc]!=match) {
  450.         ch=script[pc++];
  451.         if(ch==0) serror("Umatched quote.");
  452.         if(ch=='\\') {
  453.           if(script[pc]<='7' && script[pc]>='0' &&
  454.             script[pc+1]<='7' && script[pc+1]>='0' &&
  455.             script[pc+2]<='7' && script[pc+2]>='0' ) {
  456.             index=0;
  457.             for(p=0;p<3;p++) {
  458.               index=8*index+script[pc++]-'0';
  459.             }
  460.             pc--;
  461.             ch=index;
  462.           }
  463.           else if(script[pc]=='t') ch=9;
  464.           else if(script[pc]=='r') ch=13;
  465.           else if(script[pc]=='n') ch=10;
  466.           else if(script[pc]=='b') ch=8;
  467.           else if(script[pc]=='f') ch=12;
  468.           else if(script[pc]=='"') ch='"';
  469.           else if(script[pc]=='^') ch='^';
  470.           else if(script[pc]=='\'') ch='\'';
  471.           else if(script[pc]=='\\') ch=script[pc];
  472.           else serror("Malformed escaped character");
  473.           pc++;
  474.         }
  475.         else if(ch=='^') {
  476.           ch=script[pc];
  477.           if(ch!='^' && ch!='"' && ch!='\'' && ch!='\\' ) {
  478.             ch=ch&31; /* Control char */
  479.           }
  480.           pc++;
  481.         }
  482.         p=strlen(string);
  483.         string[p++]=ch;
  484.         string[p]=0;
  485.       }
  486.       pc++; /* Space over quote */
  487.     }
  488.     else {
  489.       p=strlen(string);
  490.       string[p++]=script[pc++];
  491.       string[p]=0;
  492.     }
  493.   }
  494. }
  495.  
  496. /* Get a value, multiply by a hundred (for time values) */
  497. unsigned long getdvalue() {
  498.   float f;
  499.   getstring();
  500.   skipspaces();
  501.   sscanf(string,"%f",&f);
  502.   f+=0.00001; /* Rounding errors */
  503.   return(100.0*f);
  504. }
  505.  
  506. void dolet() {
  507.   unsigned char index,svar=0;
  508.   if(script[pc]=='$') {
  509.     svar=1;
  510.     pc++;
  511.   }
  512.   index=script[pc++];
  513.   if(index>'z' || index<'a') serror("Bad variable name");
  514.   index-='a';
  515.   skipspaces();
  516.   gettoken();
  517.   if(strcmp(token,"=")!=0) serror("Bad LET assignment, '=' missing");
  518.   skipspaces();
  519.   if(svar) {
  520.     getstring();
  521.     strcpy(stringvars[index],string);
  522.   }
  523.   else {
  524.     intvars[index]=getvalue();
  525.   }
  526. }
  527.  
  528. /* See documentation for doXXX() functions */
  529. int dowaitquiet() {
  530.   unsigned long timeout,timequiet,quiet,now;
  531.   int c,quit;
  532.   timeout=htime()+getdvalue();
  533.   quiet=getdvalue();
  534.   timequiet=htime()+quiet;
  535.   quit=1;
  536.   while(quit==1) {
  537.     now=htime();
  538.     c=getonebyte();
  539.     if(c!= -1) timequiet=now+quiet;
  540.     if(now>=timequiet) quit=0;
  541.     if(now>=timeout) quit=255;
  542.   }
  543.   return(quit);
  544. }
  545.  
  546. int dowaitfor() {
  547.   char strings[20][80];
  548.   char buffer[128];
  549.   unsigned long timeout;
  550.   int a,b,c;
  551.   b=0;
  552.   buffer[127]=0;
  553.   skipspaces();
  554.   timeout=htime()+getdvalue();
  555.   while(script[pc]==',' || script[pc]=='$' || script[pc]=='"' ||
  556.         script[pc]=='\'' ) {
  557.     if(script[pc]==',') pc++;
  558.     getstring();
  559.     skipspaces();
  560.     strcpy(strings[b],string);
  561.     if(ignorecase) {
  562.       for(a=0;a<strlen(strings[b]);a++) {
  563.         if(strings[b][a]>='A' && strings[b][a]<='Z') {
  564.           strings[b][a]=strings[b][a]-'A'+'a';
  565.         }
  566.       }
  567.     }
  568.     b++;
  569.   }
  570.   strings[b][0]=0;
  571.   while(htime()<timeout) {
  572.     c=getonebyte();
  573.     if(c!= -1) {
  574.       if(ignorecase) {
  575.         if(c>='A' && c<='Z') c=c-'A'+'a';
  576.       }
  577.       for(a=0;a<126;a++) buffer[a]=buffer[a+1];
  578.       buffer[126]=c;
  579.       b=0;
  580.       while(strings[b][0]) {
  581.         c=strlen(strings[b]);
  582.         a=c-1;
  583.         while(a>=0 && strings[b][a]==buffer[127-c+a]) a--;
  584.         if(a<0) return(b);
  585.         b++;
  586.       }
  587.     }
  588.   }
  589.   return(-1);
  590. }
  591.  
  592. /* Parse script for "on" or "off" wich are tokens, not strings */
  593. BOOL getonoroff() {
  594.   gettoken();
  595.   if(strcmp(token,"on")==0) return(1);
  596.   if(strcmp(token,"off")==0) return(0);
  597.   serror("Bad value (should be on or off)");
  598. }
  599.  
  600. void setcom() {
  601.   stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | CLOCAL | PARENB);
  602.   stbuf.c_cflag |= (speed | bits | CREAD | clocal | parity | stopbits );
  603.   if (ioctl(comfd, TCSETA, &stbuf) < 0) {
  604.     serror("Can't ioctl set device");
  605.     ext(1);
  606.   }
  607. }
  608.  
  609. void doset() {
  610.   struct termio console;
  611.   int a,b;
  612.   gettoken();
  613.   if(strcmp(token,"echo")==0) {
  614.     a=0;
  615.     if(getonoroff()) a=ECHO|ECHOE;
  616.     if(ioctl(0, TCGETA, &console)<0) {
  617.       fprintf(stderr,"Can't ioctl FD zero!\n");
  618.       ext(1);
  619.     }
  620.     console.c_lflag &= ~(ECHO | ECHOE);
  621.     console.c_lflag |= a;
  622.     ioctl(0, TCSETA, &console);
  623.   }
  624.   else if(strcmp(token,"senddelay")==0) {
  625.     senddelay=10000L*getdvalue();
  626.   }
  627.   else if(strcmp(token,"clocal")==0) {
  628.     clocal=0;
  629.     if(getonoroff()) clocal=CLOCAL;
  630.     setcom();
  631.   }
  632.   else if(strcmp(token,"umask")==0) {
  633.     getstring();
  634.     sscanf(string,"%o",&a);
  635.     umask(0777-a);
  636.   }
  637.   else if(strcmp(token,"verbose")==0) {
  638.     verbose=getonoroff();
  639.   }
  640.   else if(strcmp(token,"comecho")==0) {
  641.     comecho=getonoroff();
  642.   }
  643.   else if(strcmp(token,"ignorecase")==0) {
  644.     ignorecase=getonoroff();
  645.   }
  646.   else if(strcmp(token,"com")==0) {
  647.     getstring();
  648.     a=0;
  649.     b=0;
  650.     while(string[b]>='0' && string[b]<='9') {
  651.       a=10*a+string[b++]-'0';
  652.     }
  653.     if(string[b]) {
  654.       if(string[b]>='A' && string[b]<='Z') string[b]=string[b]-'A'+'a';
  655.       switch(string[b]) {
  656.         case 'n': parity=0; break;
  657.         case 'e': parity=PARENB; break;
  658.         case 'o': parity=PARENB|PARODD; break;
  659.         default : serror("Parity can only ben E, N, or O");
  660.       }
  661.       b++;
  662.       if(string[b]) {
  663.         switch(string[b]) {
  664.           case '5' : bits=CS5; break;
  665.           case '6' : bits=CS6; break;
  666.           case '7' : bits=CS7; break;
  667.           case '8' : bits=CS8; break;
  668.           default : serror("Bits can only be 5, 6, 7, or 8");
  669.         }
  670.         b++;
  671.         if(string[b]) {
  672.           switch(string[b]) {
  673.             case '1': stopbits=0; break;
  674.             case '2': stopbits=CSTOPB; break;
  675.             default : serror("Stop bits can only be 1 or 2");
  676.           }
  677.         }
  678.       }
  679.     }
  680.     sprintf(cspeed,"%d",a);
  681.     switch(a) {
  682.       case 110: speed = B110;break;
  683.       case 150: speed = B150;break;
  684.       case 300: speed = B300;break;
  685.       case 1200: speed = B1200;break;
  686.       case 2400: speed = B2400;break;
  687.       case 4800: speed = B4800;break;
  688.       case 9600: speed = B9600;break;
  689.       case 19200: speed = B19200;break;
  690.       case 38400: speed = B38400;break;
  691.       default: serror("Invalid baudrate");
  692.     }
  693.     setcom();
  694.   }
  695. }
  696.  
  697. void dogoto() {
  698.   int gonethruonce=0,quitsearch=0;
  699.   char label[80];
  700.   getstring();
  701.   strcpy(label,string);
  702.   skipline();
  703.   while(quitsearch==0) {
  704.     if(script[pc]==0) {
  705.       if(gonethruonce==0) {
  706.         gonethruonce=1;
  707.         pc=0;
  708.       }
  709.       else {
  710.         sprintf(msg,"Label \"%s\" not found",label);
  711.         serror(msg);
  712.       }
  713.     }
  714.     gettoken();
  715.     if(strcmp(token,"label")==0) {
  716.       getstring();
  717.       if(strcmp(string,label)==0) quitsearch=1;
  718.     }
  719.     if(quitsearch==0) skipline();
  720.   }
  721. }
  722.  
  723. void dogosub() {
  724.   int a;
  725.   if(preturn==MAXGOSUBS) serror("Reached maximum GOSUB depth");
  726.   a=pc;
  727.   while(script[a]!='\n') a++;
  728.   returns[preturn++]=a;
  729.   dogoto();
  730. }
  731.  
  732. void doreturn() {
  733.   if(preturn==0) serror("RETURN without gosub");
  734.   pc=returns[--preturn];
  735. }
  736.  
  737. /* Gets arguments and returns 0 for a string, 1 for an int. Used with if */
  738. unsigned char getonearg() {
  739.   if(script[pc]=='"' || script[pc]=='\'' || script[pc]=='$' ) {
  740.     getstring();
  741.     return(0);
  742.   }
  743.   else {
  744.     number=getvalue();
  745.     return(1);
  746.   }
  747. }
  748.  
  749. void doif() {
  750.   char stringarg[STRINGL];
  751.   char tokencopy[MAXTOKEN];
  752.   int intarg;
  753.   skipspaces();
  754.   ifres=0;
  755.   if(getonearg()) {
  756.     intarg=number;
  757.     gettoken();
  758.     skipspaces();
  759.     if(getonearg()!=1) serror("Comparison mis-match");
  760.     if(strcmp(token,"<")==0) {
  761.       if(intarg<number) ifres=1;
  762.     }
  763.     else if(strcmp(token,"=")==0) {
  764.       if(intarg==number) ifres=1;
  765.     }
  766.     else if(strcmp(token,">")==0) {
  767.       if(intarg>number) ifres=1;
  768.     }
  769.     else if(strcmp(token,"!=")==0) {
  770.       if(intarg!=number) ifres=1;
  771.     }
  772.   }
  773.   else {
  774.     strcpy(stringarg,string);
  775.     gettoken();
  776.     strcpy(tokencopy,token);
  777.     skipspaces();
  778.     if(getonearg()!=0) serror("Comparison mis-match");
  779.     if(strcmp(tokencopy,"<")==0) {
  780.       if(strcmp(stringarg,string)<0) ifres=1;
  781.     }
  782.     else if(strcmp(tokencopy,"=")==0) {
  783.       if(strcmp(stringarg,string)==0) ifres=1;
  784.     }
  785.     else if(strcmp(tokencopy,">")==0) {
  786.       if(strcmp(stringarg,string)>0) ifres=1;
  787.     }
  788.     else if(strcmp(tokencopy,"!=")==0) {
  789.       if(strcmp(stringarg,string)!=0) ifres=1;
  790.     }
  791.   }
  792.   if(!ifres) skipline();
  793. }
  794.  
  795. /* Parse script to find integer variable index (ie.: a=0, z=25) */
  796. int getintindex() {
  797.   int index;
  798.   skipspaces();
  799.   if(script[pc]=='$') serror("Requires an integer variable");
  800.   index=script[pc++];
  801.   if(index>'z' || index<'a') serror("Malformed variable name");
  802.   return(index-'a');
  803. }
  804.  
  805. /* Parse script to find string variable index (ie.: $a=0, $z=25) */
  806. int getstringindex() {
  807.   int index;
  808.   skipspaces();
  809.   if(script[pc++]!='$') serror("Requires a string variable");
  810.   index=script[pc++];
  811.   if(index>'z' || index<'a') serror("Malformed variable name");
  812.   return(index-'a');
  813. }
  814.  
  815. void doget() {
  816.   char terminators[STRINGL];
  817.   int a,b,c,index;
  818.   int goahead=1;
  819.   unsigned long timeout;
  820.   timeout=htime()+getdvalue();
  821.   getstring();
  822.   strcpy(terminators,string);
  823.   index=getstringindex();
  824.   string[0]=0;
  825.   b=0;
  826.   resultcode=0;
  827.   while(goahead && htime()<timeout) {
  828.     c=getonebyte();
  829.     if(c!= -1) {
  830.       for(a=0;a<strlen(terminators);a++) {
  831.         if(c==terminators[a]) goahead=0;
  832.       }
  833.       if(goahead==0 && b==0) goahead=1; /* Ignore terminators if nothing yet */
  834.       else if(goahead) {
  835.         string[b++]=c;
  836.         string[b]=0;
  837.       }
  838.     }
  839.   }
  840.   if(goahead) resultcode= -1;
  841.   strcpy(stringvars[index],string);
  842. }
  843.  
  844. void doinc() {
  845.   intvars[getintindex()]++;
  846. }
  847.  
  848. void dodec() {
  849.   intvars[getintindex()]--;
  850. }
  851.  
  852. void doinput() {
  853.   gets(stringvars[getstringindex()]);
  854. }
  855.  
  856. void doprint(int channel) {
  857.   skipspaces();
  858.   msg[0]=0;
  859.   while(script[pc]!=' ' && script[pc]!='\t' && script[pc]!='\n') {
  860.     if(script[pc]==',') pc++;
  861.     else {
  862.       if(script[pc]=='"' || script[pc]=='\'' || script[pc]=='$' ) {
  863.         getstring();
  864.         strcat(msg,string);
  865.       }
  866.       else {
  867.         sprintf(string,"%ld",getvalue());
  868.         strcat(msg,string);
  869.       }
  870.     }
  871.   }
  872.   switch(channel) {
  873.     case 1: printf("%s",msg); fflush(stdout); break;
  874.     case 2: fputs(msg,stderr); break;
  875.     case 3: vmsg(msg); break;
  876.     case 4: 
  877.       if(filep==NULL) serror("File not opened");
  878.       fputs(msg,filep);
  879.       break;
  880.   }
  881. }
  882.  
  883. void doclose() {
  884.   gettoken();
  885.   if(strcmp(token,"hardcom")==0) {
  886.     if(comfd== -1) serror("Com device not open");
  887.     vmsg("Closing device");
  888.     if (ioctl(comfd, TCSETA, &svbuf) < 0) {
  889.       fprintf(stderr,"Can't ioctl set device %s.\n",device);
  890.       ext(1);
  891.     }
  892.     close(comfd);
  893.     comfd= -1;
  894.   }
  895.   else if(strcmp(token,"com")==0) {
  896.     if(comfd== -1) serror("Com device not open");
  897.     vmsg("Closing com fd");
  898.     close(comfd);
  899.     comfd= -1;
  900.   }
  901.   else if(strcmp(token,"file")==0) {
  902.     if(filep==NULL) serror("Log file not open");
  903.     fclose(filep);
  904.     filep=NULL;
  905.   }
  906. }
  907.  
  908. void doopen() {
  909.   gettoken();
  910.   if(strcmp(token,"com")==0) {
  911.     if(comfd!= -1) serror("Com device already open");
  912.     getstring();
  913.     strcpy(device,string);
  914.     if(strcmp(device,"-")) {
  915.       if ((comfd = open(device, O_RDWR|O_EXCL|O_NDELAY)) <0) {
  916.         fprintf(stderr,"Can't open device %s.\n",device);
  917.         ext(1);
  918.       }
  919.     }
  920.     else comfd=0;
  921.     if (ioctl (comfd, TCGETA, &svbuf) < 0) {
  922.       fprintf(stderr,"Can't ioctl get device %s.\n",device);
  923.       ext(1);
  924.     }
  925.     ioctl(comfd, TCGETA, &stbuf);
  926.     stbuf.c_iflag &= ~(IGNCR | ICRNL | IUCLC | INPCK | IXON | IXANY | IGNPAR );
  927.     stbuf.c_oflag &= ~(OPOST | OLCUC | OCRNL | ONLCR | ONLRET);
  928.     stbuf.c_lflag &= ~(ICANON | XCASE | ECHO | ECHOE | ECHONL);
  929.     stbuf.c_cc[VEOF] = 1;
  930.     setcom();
  931.     dormir(200000); /* Wait a bit (DTR raise) */
  932.     sprintf(msg,"Opened %s as FD %d baudrate:%d",device,comfd,atoi(cspeed));
  933.     vmsg(msg);
  934.   }
  935.   else if (strcmp(token,"file")==0) {
  936.     if(filep!=NULL) serror("File already open");
  937.     getstring();
  938.     if((filep=fopen(string,"a"))==NULL) serror("Could not open file");
  939.   }
  940.   else serror("OPEN only takes com or file argument");
  941. }
  942.  
  943. int doscript() {
  944.   int a,b,c;
  945.   int exitcode=0;
  946.   char line[STRINGL];
  947.   pc=0;
  948.   while(script[pc]) {
  949.     if(script[pc]=='\n') pc++;
  950.     lastpc=pc;
  951.     skipspaces();
  952.     if(verbose) printwhere();
  953.     if(gettoken()) serror("Could not gettoken()");
  954.     skipspaces();
  955.     if(strcmp(token,"rem")==0) {
  956.       skipline();
  957.     }
  958.     else if (strcmp(token,"label")==0) {
  959.       getstring(); /* Get rid of keyword */
  960.     }
  961.     else if(strcmp(token,"open")==0) {
  962.       doopen();
  963.     }
  964.     else if(strcmp(token,"close")==0) {
  965.       doclose();
  966.     }
  967.     else if(strcmp(token,"exec")==0) {
  968.       getstring();
  969.       strcpy(msg,"exec ");
  970.       strcat(msg,string); /* Let sh do all the command line work! */
  971.       execl("/bin/sh","sh","-c",msg,(char *)0);
  972.       serror("Could not execl!");
  973.     }
  974.     else if(strcmp(token,"exit")==0) {
  975.       ext(getvalue());
  976.     }
  977.     else if(strcmp(token,"testkey")==0) {
  978.       dotestkey();
  979.     }
  980.     else if(strcmp(token,"kill")==0) {
  981.       a=getvalue();
  982.       resultcode=kill(getvalue(),a);
  983.     }
  984.     else if(strcmp(token,"fork")==0) {
  985.       resultcode=fork();
  986.     }
  987.     else if(strcmp(token,"hset")==0) {
  988.       hset=0;
  989.       hstart=time(0);
  990.       hset=htime()-getvalue();
  991.     }
  992.     else if(strcmp(token,"cd")==0) {
  993.       getstring();
  994.       resultcode=chdir(string);
  995.     }
  996.     else if(strcmp(token,"putenv")==0) {
  997.       getstring();
  998.       strcpy(line,string);
  999.       resultcode=putenv(line); /* putenv can't read from global string[] */
  1000.     }
  1001.     else if(strcmp(token,"wait")==0) {
  1002.       resultcode=wait(0);
  1003.     }
  1004.     else if(strcmp(token,"system")==0) {
  1005.       getstring();
  1006.       system(string);
  1007.     }
  1008.     else if(strcmp(token,"input")==0) {
  1009.       doinput();
  1010.     }
  1011.     else if(strcmp(token,"get")==0) {
  1012.       doget();
  1013.     }
  1014.     else if(strcmp(token,"print")==0) {
  1015.       doprint(1);
  1016.     }
  1017.     else if(strcmp(token,"eprint")==0) {
  1018.       doprint(2);
  1019.     }
  1020.     else if(strcmp(token,"lprint")==0) {
  1021.       doprint(3);
  1022.     }
  1023.     else if(strcmp(token,"fprint")==0) {
  1024.       doprint(4);
  1025.     }
  1026.     else if(strcmp(token,"if")==0) {
  1027.       doif();
  1028.     }
  1029.     else if(strcmp(token,"else")==0) {
  1030.       if(ifres) skipline();
  1031.     }
  1032.     else if(strcmp(token,"gosub")==0) {
  1033.       dogosub();
  1034.     }
  1035.     else if(strcmp(token,"return")==0) {
  1036.       doreturn();
  1037.     }
  1038.     else if(strcmp(token,"goto")==0) {
  1039.       dogoto();
  1040.     }
  1041.     else if(strcmp(token,"waitfor")==0) {
  1042.       resultcode=dowaitfor();
  1043.     }
  1044.     else if(strcmp(token,"waitquiet")==0) {
  1045.       resultcode=dowaitquiet();
  1046.     }
  1047.     else if(strcmp(token,"set")==0) {
  1048.       doset();
  1049.     }
  1050.     else if(strcmp(token,"dec")==0) {
  1051.       dodec();
  1052.     }
  1053.     else if(strcmp(token,"inc")==0) {
  1054.       doinc();
  1055.     }
  1056.     else if(strcmp(token,"let")==0) {
  1057.       dolet();
  1058.     }
  1059.     else if(strcmp(token,"send")==0) {
  1060.       getstring();
  1061.       writecom(string);
  1062.     }
  1063.     else if(strcmp(token,"sleep")==0) {
  1064.       a=getdvalue();
  1065.       if(a<10000) dormir(10000L*a);
  1066.       else sleep(a/100); /* I guess it's the same.  Oh well, past 10secs,
  1067.                             use sleep instead.  */
  1068.     }
  1069.     else serror("What's that, governor?");
  1070.     skipspaces();
  1071.     while(script[pc]=='\n') pc++;
  1072.   }
  1073.   return(exitcode);
  1074. }
  1075.  
  1076. int main(int argc,char *argv[]) {
  1077.   int a,b,i,len;
  1078.   int speed;
  1079.   unsigned char ch;
  1080.   unsigned char terminator='\n';
  1081.   unsigned char line[STRINGL];
  1082.   FILE *fp;
  1083.   hstart=time(0);
  1084.   hset=htime();
  1085.   preturn=0;
  1086.   filep=NULL;
  1087.   scriptspace=4096;
  1088.   ioctl(1, TCGETA, &cons);
  1089.   if((script=(char *)malloc(scriptspace))==NULL) {
  1090.     fprintf(stderr,"Could not malloc()!\n");
  1091.     ext(1);
  1092.   }
  1093.   for(a=0;a<26;a++) {
  1094.     intvars[a]=0;
  1095.     stringvars[a][0]=0;
  1096.   }
  1097.   strcpy(cspeed,"2400");
  1098.   scriptfile[0]=0;
  1099.   for(a = 1; a < argc; a++) {
  1100.     if(strcmp(argv[a],"-b")==0) strcpy(cspeed,argv[++a]);
  1101.     else if(strcmp(argv[a],"-t")==0) {
  1102.       terminator=argv[++a][0];
  1103.       sprintf(msg,"Alternate line terminator set to \"%c\"",terminator);
  1104.       vmsg(msg);
  1105.     }
  1106.     else if(strcmp(argv[a],"-d")==0) strcpy(device,argv[++a]);
  1107.     else if(strcmp(argv[a],"-e")==0) comecho=1;
  1108.     else if(strcmp(argv[a],"-v")==0) verbose=1;
  1109.     else if(strcmp(argv[a],"-s")==0) { 
  1110.       scriptspace=strlen(argv[++a])+1;
  1111.       if((script=(char *)realloc(script,scriptspace))==0) {
  1112.         fprintf(stderr,"Could not malloc()!\n");
  1113.         ext(1);
  1114.       }
  1115.       strcpy(script,argv[a]);
  1116.       for(a=0;a<scriptspace;a++) {
  1117.         if(script[a]==terminator) script[a]='\n';
  1118.       }
  1119.     }
  1120.     else {
  1121.       strcpy(scriptfile,argv[a]);
  1122.       a=argc;
  1123.     }
  1124.   }
  1125.   if(scriptfile[0]) {
  1126.     if((fp=fopen(scriptfile,"r"))==NULL) {
  1127.       fprintf(stderr,"Could not open scriptfile \"%s\".\n",scriptfile);
  1128.       ext(1);
  1129.     }
  1130.     i=strlen(script);
  1131.     while((fgets(line,STRINGL-1,fp))!=NULL) {
  1132.       b=strlen(line);
  1133.       if((scriptspace-i)<STRINGL) {
  1134.         scriptspace+=STRINGL+STRINGL;
  1135.         if((script=(char *)realloc(script,scriptspace))==NULL) {
  1136.           fprintf(stderr,"Could not realloc()!\n");
  1137.           ext(1);
  1138.         }
  1139.       }
  1140.       for(a=0;a<b;a++) {
  1141.         script[i]=line[a];
  1142.         if(script[i]==terminator) script[i]='\n';
  1143.         i++;
  1144.       }
  1145.     }
  1146.     script[i]=0;
  1147.     fclose(fp);
  1148.   }
  1149.   if(script[0]) {
  1150.     i=strlen(script)-1;
  1151.     while((script[i]=='\n' || script[i]==' ' || script[i]=='\t') && i!=0) i--;
  1152.     script[++i]='\n';
  1153.     script[++i]=0;
  1154.   }
  1155.   if(verbose) {
  1156.     fprintf(stderr,"argc:%d\n",argc);
  1157.     for(a=0;a<argc;a++) {
  1158.       fprintf(stderr,"argv[%d]=%s\n",a,argv[a]);
  1159.     }
  1160.     fprintf(stderr,"dcon ---Script---\n");
  1161.     a=0; b=0; ch='\n';
  1162.     i=strlen(script);
  1163.     while(a<scriptspace) {
  1164.       if(ch=='\n' && script[a]!=0) {
  1165.         fprintf(stderr,"%4d ",++b);
  1166.       }
  1167.       ch=script[a++];
  1168.       fputc(ch,stderr);
  1169.     }
  1170.     fprintf(stderr,"dcon ---End of script---\n");
  1171.   }
  1172.   if(script[0]==0) {
  1173.     fprintf(stderr,"No script!\n");
  1174.     ext(1);
  1175.   }
  1176.   a=doscript();
  1177.   dormir(200000);
  1178.   if(comfd!= -1) close(comfd);
  1179.   sprintf(msg,"Exit with code %d.\n",a);
  1180.   vmsg(msg);
  1181.   ext(a);
  1182. }
  1183.